﻿using UnityEditor;
using UnityEngine;
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

public enum TargetPlatform{
    IOS,
    Window,
    Android,
    inValid,
}

public class Packager
{
    public static string platform = string.Empty;

    public static bool bLoadAB = false;

    private static bool bEncodeLua = false;

    private static bool bAssetBundle = true;

    public static TargetPlatform curTarget = TargetPlatform.IOS;


    public static TargetPlatform CurTarget
    {
        get{
            
            return curTarget;
        }

        set
        {

        }

    }
    /// <summary>
    /// 载入素材
    /// </summary>
    static UnityEngine.Object LoadAsset(string file)
    {
        if (file.EndsWith(".lua")) file += ".txt";
        return AssetDatabase.LoadMainAssetAtPath("Assets/Builds/" + file);
    }

    public static BuildTarget getBuildTarget()
    {
        BuildTarget target = BuildTarget.StandaloneWindows;
        switch (curTarget)
        {
            case TargetPlatform.IOS:
                target = BuildTarget.iOS;
                break;
            case TargetPlatform.Android:
                target = BuildTarget.Android;
                break;
        }
        return target;
    }

    /// <summary>
    /// 生成绑定素材
    /// </summary>
    public static void BuildAssetResource()
    {
        //1.生成AB包
        BuildTarget target = getBuildTarget();
        Packager.GenerateAB(target);
        
        ////2.复制 lua 文件
        //string luaDataPath = Application.dataPath + "/StreamingAssets/";
        //Recursive(luaDataPath);
        //int n = 0;
        //foreach (string f in files)
        //{
        //    if (f.EndsWith(".meta")) continue;
        //    string newfile = f.Replace(luaDataPath, "");
        //    string newpath = resPath + "/" + newfile;
        //    string path = Path.GetDirectoryName(newpath);
        //    if (!Directory.Exists(path)) Directory.CreateDirectory(path);

        //    if (File.Exists(newpath))
        //    {
        //        File.Delete(newpath);
        //    }
        //    if (Packager.bEncodeLua)
        //    {
        //        UpdateProgress(n++, files.Count, newpath);
        //        EncodeLuaFile(f, newpath, isWin);
        //    }
        //    else
        //    {
        //        File.Copy(f, newpath, true);
        //    }
        //}
        //EditorUtility.ClearProgressBar();


    }

    //生成AB包
    public static void GenerateAB(BuildTarget target)
    {
        string targetFolder = Packager.GetPlatformFolderForAssetBundles(target);
        string resPath = Application.streamingAssetsPath + "/AssetBundles/" + targetFolder;

        if (!Directory.Exists(resPath))
            Directory.CreateDirectory(resPath);

        if (Packager.bAssetBundle)
            BuildPipeline.BuildAssetBundles(resPath, BuildAssetBundleOptions.ChunkBasedCompression , target);
    }

    //清除AB包
    public static void ClearABFolder()
    {
        string resPath = Application.streamingAssetsPath + "/AssetBundles/"+ Packager.GetPlatformFolderForAssetBundles(Packager.getBuildTarget());
        if (Directory.Exists(resPath))
        {
            Directory.Delete(resPath, true);
        }
    }

    /// <summary>
    /// 数据目录
    /// </summary>
    static string AppDataPath
    {
        get { return Application.dataPath.ToLower(); }
    }

    /// <summary>
    /// 遍历目录及其子目录
    /// </summary>
    static void Recursive(string path)
    {
        string[] names = Directory.GetFiles(path);
        string[] dirs = Directory.GetDirectories(path);
        foreach (string filename in names)
        {
            string ext = Path.GetExtension(filename);
            if (ext.Equals(".meta")) continue;
        }
        foreach (string dir in dirs)
        {
            Recursive(dir);
        }
    }

    public static void UpdateProgress(int progress, int progressMax, string desc)
    {
        string title = "Processing...[" + progress + " - " + progressMax + "]";
        float value = (float)progress / (float)progressMax;
        EditorUtility.DisplayProgressBar(title, desc, value);
    }

    static void EncodeLuaFile(string srcFile, string outFile, bool isWin)
    {
        if (!srcFile.ToLower().EndsWith(".lua"))
        {
            File.Copy(srcFile, outFile, true);
            return;
        }
        string luaexe = string.Empty;
        string args = string.Empty;
        string exedir = string.Empty;
        string currDir = Directory.GetCurrentDirectory();
        if (Application.platform == RuntimePlatform.WindowsEditor)
        {
            luaexe = "luajit.exe";
            args = "-b " + srcFile + " " + outFile;
            exedir = AppDataPath + "/../../Tools/LuaEncoder/luajit/";
        }
        else if (Application.platform == RuntimePlatform.OSXEditor)
        {
            luaexe = "./luac";
            args = "-o " + outFile + " " + srcFile;
            exedir = AppDataPath + "/../../Tools/LuaEncoder/luavm/";
        }
        Directory.SetCurrentDirectory(exedir);
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = luaexe;
        info.Arguments = args;
        info.WindowStyle = ProcessWindowStyle.Hidden;
        info.UseShellExecute = isWin;
        info.ErrorDialog = true;
        UnityEngine.Debug.Log(info.FileName + " " + info.Arguments);

        Process pro = Process.Start(info);
        pro.WaitForExit();
        Directory.SetCurrentDirectory(currDir);
    }

    public static string GetPlatformFolderForAssetBundles(BuildTarget target)
    {
        switch (target)
        {
            case BuildTarget.Android:
                return "Android";
            case BuildTarget.iOS:
                return "iOS";
            case BuildTarget.WebPlayer:
                return "WebPlayer";
            case BuildTarget.StandaloneWindows:
            case BuildTarget.StandaloneWindows64:
                return "Windows";
            case BuildTarget.StandaloneOSXIntel:
            case BuildTarget.StandaloneOSXIntel64:
            case BuildTarget.StandaloneOSXUniversal:
                return "OSX";
            // Add more build targets for your own.
            // If you add more targets, don't forget to add the same platforms to GetPlatformFolderForAssetBundles(RuntimePlatform) function.
            default:
                return null;
        }
    }

    public static Hashtable BuildAssetMarks()
    {
        Hashtable lstAllBuildFile = new Hashtable();

        string sourcePath = Application.dataPath + "/ABRes";
        List<string> fileSystemEntries = new List<string>();

        fileSystemEntries
            .AddRange(Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)
                          .Select(d => d + "\\"));
        fileSystemEntries
            .AddRange(Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories));

        for (int i = 0; i < fileSystemEntries.Count; i++ )
        {
            string filePath = fileSystemEntries[i];
            string ext = Path.GetExtension(filePath);
            string extLower = Path.GetExtension(filePath).ToLower();

            string assetPath = filePath.Replace(Application.dataPath, "Assets");
            AssetImporter import = AssetImporter.GetAtPath(assetPath);
            if (import != null)
            {
                assetPath = assetPath.Replace(ext, "");
                UnityEngine.Debug.Log("Setting a AB name: " + assetPath);

                if (extLower.Equals(".prefab") || extLower.Equals(".png") || extLower.Equals(".unity")
                    || extLower.Equals(".fbx") || extLower.Equals(".tga") || extLower.Equals(".controller")
                    || extLower.Equals(".overridecontroller"))
                    
                {
                    import.assetBundleName = assetPath;

                    filePath = filePath.Replace("\\", "/");
                    filePath = filePath.Replace(Application.dataPath, "Assets");
                    lstAllBuildFile.Add(filePath, true);
                }
                else
                {
                    import.assetBundleName = "";
                }
                UpdateProgress(i, fileSystemEntries.Count, assetPath);
            }
        }
        EditorUtility.ClearProgressBar();

        return lstAllBuildFile;
    }

    public static void SaveAllRoot(Hashtable tabBuildFile)
    {
        if (tabBuildFile.Count <= 0) return;

        List<string> lstRoot = new List<string>();
        List<string> lstDep = new List<string>();

        IDictionaryEnumerator em = tabBuildFile.GetEnumerator();
        while(em.MoveNext())
        {
            string filePath = em.Key.ToString();

            string assetPath = filePath.Replace(Application.dataPath, "Assets");

            string extLower = Path.GetExtension(assetPath).ToLower();

            if (extLower.Equals(".prefab") || extLower.Equals(".png") || extLower.Equals(".unity")
                    || extLower.Equals(".fbx") || extLower.Equals(".tga") || extLower.Equals(".controller")
                    || extLower.Equals(".overridecontroller"))
            {
                string[] depArr = AssetDatabase.GetDependencies(assetPath);

                for (int i = 0; i < depArr.Length; i++)
                {
                    if( !depArr[i].Equals(assetPath) )
                    {
                        if( tabBuildFile.ContainsKey(depArr[i]) )
                        {
                            if (!lstDep.Contains(depArr[i]))
                            {
                                lstDep.Add(depArr[i]);
                            }
                        }
                    }
                }
            }
        }
        em = tabBuildFile.GetEnumerator();
        while(em.MoveNext())
        {
            string filePath = em.Key.ToString();

            string assetPath = filePath.Replace(Application.dataPath, "Assets");

            if( !lstDep.Contains(em.Key.ToString()) )
            {
                lstRoot.Add(em.Key.ToString());
            }
        }

        BuildTarget target = getBuildTarget();
        string targetFolder = Packager.GetPlatformFolderForAssetBundles(target);
        string resPath = Application.streamingAssetsPath + "/AssetBundles/" + targetFolder + "/ABAssetRootFile.txt";

        if (File.Exists(resPath))
            File.Delete(resPath);

        string fileName;
        FileStream fs = new FileStream(resPath, FileMode.CreateNew);
        StreamWriter sw = new StreamWriter(fs);
        for (int i = 0; i < lstRoot.Count; i++)
        {
            fileName = lstRoot[i];
            fileName = Path.GetDirectoryName(fileName) + "/" + Path.GetFileNameWithoutExtension(fileName);

            sw.WriteLine(fileName);
        }
        sw.Close();
    }
}